/**
 * 
 */
package it.rainbowbreeze.polygen.data.webservice;

import it.rainbowbreeze.libs.net.IRainbowRestfulClient.ServerResponse;
import it.rainbowbreeze.polygen.common.LogFacility;
import it.rainbowbreeze.polygen.common.ResultOperation;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.Random;

import static it.rainbowbreeze.libs.common.RainbowContractHelper.checkNotNull;

/**
 * @author Alfredo "Rainbowbreeze" Morresi
 */
public class WebserviceManager {
    // ------------------------------------------ Private Fields
    private static final String LOG_HASH = WebserviceManager.class.getSimpleName();
    
    private final LogFacility mLogFacility;
    private final RestfulClient mRestfulClient;
    private final Random mRandom;
    
    
    // -------------------------------------------- Constructors
    public WebserviceManager(LogFacility logFacility,
            RestfulClient restfulClient) {
        mLogFacility = checkNotNull(logFacility, "LogFacility");
        mRestfulClient = checkNotNull(restfulClient, "RestfulClient");
        mRandom = new Random();
    }

    
    // --------------------------------------- Public Properties

    
    // ------------------------------------------ Public Methods
    
    public ResultOperation<String> getMessageFromSection(String url) {
        ResultOperation<String> result = prepareAndSendRequest(url);
        if (result.hasErrors()) {
            mLogFacility.e(LOG_HASH, "Cannot read new message. Cause: " + result.getReturnCode());
        } else {
            mLogFacility.v(LOG_HASH, "Message read!");
        }
        return result;
    }
    
    
    // ----------------------------------------- Private Methods
    private ResultOperation<String> prepareAndSendRequest(
            String url) {
        
        ServerResponse serverResponse;
        try {
            //append random value to obtain new sentences every time
            serverResponse = mRestfulClient.requestGet(url + "?r=" + mRandom.nextInt());
        } catch (IOException e) {
            return new ResultOperation<String>(e, ResultOperation.RETURNCODE_ERROR_COMMUNICATION);
        }

        if (hasError(serverResponse)) {
            return processError(serverResponse);
        }

        ResultOperation<String> result = new ResultOperation<String>(serverResponse.getResponseMessage());
        return result;
    }
    
    
    /**
     * Verifies if the webservice response contains errors
     * 
     * @param serverResponse
     * @return
     */
    protected boolean hasError(ServerResponse serverResponse) {
        if (null == serverResponse) return true;
        
        //first of all, checks server response code
        if (serverResponse.getResponseCode() != HttpURLConnection.HTTP_OK)
            return true;
        
        return false;
    }
    
    /**
     * Reads from webservice response the error and create appropriate object
     * 
     * @param <ResultType> the generic for {@link ResultOperation}
     * @param serverResponse the webservice response
     * @param resultType the generic for {@link ResultOperation}
     * 
     * @return a new {@link ResultOperation} object with standard error code
     */
    private ResultOperation<String> processError(
            ServerResponse serverResponse) {

        int errorReturnCode;
        Exception exception = null;

        if (null == serverResponse) {
            //http error in incapsulated in a generic communication error
            errorReturnCode = ResultOperation.RETURNCODE_ERROR_COMMUNICATION;

            //value of http error is put inside the exception
            exception = new Exception("HTTP Error " + serverResponse.getResponseCode());
            
        } else { // if (serverResponse.getResponseCode() != HttpURLConnection.HTTP_OK) {
            //http error in incapsulated in a generic communication error
            errorReturnCode = ResultOperation.RETURNCODE_ERROR_COMMUNICATION;
            //value of http error is put inside the exception
            exception = new Exception("HTTP Error " + serverResponse.getResponseCode());
            mLogFacility.v(LOG_HASH, "Network operation returns an error code " + serverResponse.getResponseCode());
        }

        ResultOperation<String> result = new ResultOperation<String>(exception, errorReturnCode);
        
        return result;
    }
}
